package com.jt808.decode.utils;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;

import java.util.List;

/**
 * Unpacking tools
 * @date 20230304
 */
public class SplitUtil {
    /**
     * Decode the terminal registration information of JT808-2011 and JT808-2013 versions
     * @param msgBuf
     * @param dataArr
     */
    public static void splitTerminalRegisterInfo(ByteBuf msgBuf, List<String> dataArr){
        dataArr.add(String.format("%s-->%s",NumberUtil.hexStr(msgBuf.readUnsignedShort(),4),"Province Id"));
        dataArr.add(String.format("%s-->%s",NumberUtil.hexStr(msgBuf.readUnsignedShort(),4),"City Id"));
        byte[] producerIdArr=new byte[5];
        msgBuf.readBytes(producerIdArr);
        dataArr.add(String.format("%s-->%s", ByteBufUtil.hexDump(producerIdArr),"Producer Id"));
        try{
            byte[] terminalTypeArr=new byte[20];
            msgBuf.readBytes(terminalTypeArr);
            dataArr.add(String.format("%s-->%s", ByteBufUtil.hexDump(terminalTypeArr),"Terminal type"));
            byte[] terminalNumber=new byte[7];
            msgBuf.readBytes(terminalNumber);
            dataArr.add(String.format("%s-->%s", ByteBufUtil.hexDump(terminalNumber),"Terminal number"));
            dataArr.add(String.format("%s-->%s",NumberUtil.hexStr(msgBuf.readUnsignedByte(),2),"Vehicle plate color"));
            byte [] plateNumber=new byte[msgBuf.readableBytes()];
            msgBuf.readBytes(plateNumber);
            dataArr.add(String.format("%s-->%s", ByteBufUtil.hexDump(plateNumber),"Vehicle plate number"));
        }catch (Exception e){
            //JT808-2011 the terminal model before the revision is 8 bytes
            msgBuf.readerIndex(9);
            byte[] terminalTypeArr=new byte[8];
            msgBuf.readBytes(terminalTypeArr);
            dataArr.add(String.format("%s-->%s", ByteBufUtil.hexDump(terminalTypeArr),"Terminal type"));
            byte[] terminalNumber=new byte[7];
            msgBuf.readBytes(terminalNumber);
            dataArr.add(String.format("%s-->%s", ByteBufUtil.hexDump(terminalNumber),"Terminal number"));
            dataArr.add(String.format("%s-->%s",NumberUtil.hexStr(msgBuf.readUnsignedByte(),2),"Vehicle plate color"));
            byte [] plateNumber=new byte[msgBuf.readableBytes()];
            msgBuf.readBytes(plateNumber);
            dataArr.add(String.format("%s-->%s", ByteBufUtil.hexDump(plateNumber),"Vehicle plate number"));
        }
    }

    /**
     * Decode the terminal registration information of JT808-2019
     * @param msgBuf
     * @param dataArr
     */
    public static void splitTerminalRegisterInfo2019(ByteBuf msgBuf, List<String> dataArr){
        dataArr.add(String.format("%s-->%s",NumberUtil.hexStr(msgBuf.readUnsignedShort(),4),"Province Id"));
        dataArr.add(String.format("%s-->%s",NumberUtil.hexStr(msgBuf.readUnsignedShort(),4),"City Id"));
        byte[] producerIdArr=new byte[11];
        msgBuf.readBytes(producerIdArr);
        dataArr.add(String.format("%s-->%s", ByteBufUtil.hexDump(producerIdArr),"Producer Id"));
        byte[] terminalTypeArr=new byte[30];
        msgBuf.readBytes(terminalTypeArr);
        dataArr.add(String.format("%s-->%s", ByteBufUtil.hexDump(terminalTypeArr),"Terminal type"));
        byte[] terminalNumber=new byte[30];
        msgBuf.readBytes(terminalNumber);
        dataArr.add(String.format("%s-->%s", ByteBufUtil.hexDump(terminalNumber),"Terminal number"));
        dataArr.add(String.format("%s-->%s",NumberUtil.hexStr(msgBuf.readUnsignedByte(),2),"Vehicle plate color"));
        byte [] plateNumber=new byte[msgBuf.readableBytes()];
        msgBuf.readBytes(plateNumber);
        dataArr.add(String.format("%s-->%s", ByteBufUtil.hexDump(plateNumber),"Vehicle plate number"));
    }

    /**
     * terminal parameter response
     * @param msgBuf
     * @param dataArr
     */
    public static void splitTerminalParameterResponse(ByteBuf msgBuf, List<String> dataArr){
        dataArr.add(String.format("%s-->%s",NumberUtil.hexStr(msgBuf.readUnsignedShort(),4),"Response serial number"));
        dataArr.add(String.format("%s-->%s",NumberUtil.hexStr(msgBuf.readUnsignedShort(),4),"Number of response parameters"));
        while (msgBuf.readableBytes()>=5){
            int itemId = Math.toIntExact(msgBuf.readUnsignedInt());
            int itemLen = msgBuf.readUnsignedByte();
            dataArr.add(String.format("%s-->%s",NumberUtil.hexStr(itemId,8),"Item Id"));
            dataArr.add(String.format("%s-->%s",NumberUtil.hexStr(itemLen,2),"Item Length"));
            if (msgBuf.readableBytes() < itemLen) {
                break;
            }
            byte [] itemArr=new byte[itemLen];
            msgBuf.readBytes(itemArr);
            dataArr.add(String.format("%s-->%s",ByteBufUtil.hexDump(itemArr),"Item Value"));
        }
    }

    /**
     * Terminal authentication
     * @param msgBuf
     * @param dataArr
     * @param versionFlag
     */
    public static void splitAuthInfo(ByteBuf msgBuf, List<String> dataArr,int versionFlag){
        if(versionFlag==1){
            int authCodeLen = msgBuf.readUnsignedByte();
            dataArr.add(String.format("%s-->%s",NumberUtil.hexStr(authCodeLen,2),"Authentication code length"));
            byte [] infoArr=new byte [authCodeLen];
            msgBuf.readBytes(infoArr);
            dataArr.add(String.format("%s-->%s",ByteBufUtil.hexDump(infoArr),"Authentication code"));
            byte [] imeiArr=new byte [15];
            msgBuf.readBytes(imeiArr);
            dataArr.add(String.format("%s-->%s",ByteBufUtil.hexDump(imeiArr),"Terminal IMEI"));
            byte [] softwareVersionArr=new byte [20];
            msgBuf.readBytes(softwareVersionArr);
            dataArr.add(String.format("%s-->%s",ByteBufUtil.hexDump(softwareVersionArr),"Software version"));
        }else {
            byte [] infoArr=new byte [msgBuf.readableBytes()];
            msgBuf.readBytes(infoArr);
            dataArr.add(String.format("%s-->%s",ByteBufUtil.hexDump(infoArr),"Authentication code"));
        }
    }

    /**
     * Split positioning package
     * @param msgBuf
     * @param dataArr
     */
    public static void splitLocationInfo(ByteBuf msgBuf, List<String> dataArr){
        splitLocation(msgBuf, dataArr);
        //Processing additional information
        if (msgBuf.readableBytes() > 0) {
            splitExtraInfo(msgBuf, dataArr);
        }
    }

    /**
     * Analyze positioning data
     * @param msgBuf
     * @param dataArr
     */
    private static void splitLocation(ByteBuf msgBuf, List<String> dataArr){
        dataArr.add(String.format("%s-->%s",NumberUtil.hexStr(msgBuf.readUnsignedInt(),8),"Alarm flag"));
        dataArr.add(String.format("%s-->%s",NumberUtil.hexStr(msgBuf.readUnsignedInt(),8),"Terminal status"));
        dataArr.add(String.format("%s-->%s",NumberUtil.hexStr(msgBuf.readUnsignedInt(),8),"Latitude"));
        dataArr.add(String.format("%s-->%s",NumberUtil.hexStr(msgBuf.readUnsignedInt(),8),"Longitude"));
        dataArr.add(String.format("%s-->%s",NumberUtil.hexStr(msgBuf.readUnsignedShort(),4),"Altitude"));
        dataArr.add(String.format("%s-->%s",NumberUtil.hexStr(msgBuf.readUnsignedShort(),4),"Speed"));
        dataArr.add(String.format("%s-->%s",NumberUtil.hexStr(msgBuf.readUnsignedShort(),4),"Direction"));
        //gnss time
        byte[] timeArr = new byte[6];
        msgBuf.readBytes(timeArr);
        dataArr.add(String.format("%s-->%s",ByteBufUtil.hexDump(timeArr),"Datetime"));
    }

    /**
     * Expand information unpacking
     * @param msgBuf
     * @param dataArr
     */
    private static void splitExtraInfo(ByteBuf msgBuf, List<String> dataArr){
        while (msgBuf.readableBytes() > 1){
            int extraInfoId = msgBuf.readUnsignedByte();
            int extraInfoLen = msgBuf.readUnsignedByte();
            dataArr.add(String.format("%s-->%s",NumberUtil.hexStr(extraInfoId,2),"Extension ID"));
            dataArr.add(String.format("%s-->%s",NumberUtil.hexStr(extraInfoLen,2),"Extension information length"));
            if (msgBuf.readableBytes() < extraInfoLen) {
                byte [] extraInfoArr=new byte[msgBuf.readableBytes()];
                msgBuf.readBytes(extraInfoArr);
                dataArr.add(String.format("%s-->%s",ByteBufUtil.hexDump(extraInfoArr),"Error Extension information"));
                break;
            }else{
                byte [] extraInfoArr=new byte[extraInfoLen];
                msgBuf.readBytes(extraInfoArr);
                dataArr.add(String.format("%s-->%s",ByteBufUtil.hexDump(extraInfoArr),"Extension information"));
            }
        }
    }
}
